package com.ygqh.baby.service.pay.app.weixin;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.Pay3Api;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.exception.WeixinPayException;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.payment.mch.RefundResult;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.IdType;
import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.AppType;
import com.ygqh.baby.ao.PayType;
import com.ygqh.baby.exception.YgException;
import com.ygqh.baby.service.FileService;
import com.ygqh.baby.service.pay.app.AppPaySuccessHandler;
import com.ygqh.baby.service.wechat.api.YgPay3Api;
import com.ygqh.baby.service.wechat.notify.PayNotifyData;
import com.ygqh.baby.service.wechat.notify.PayNotifyTemplate;
import com.ygqh.baby.service.wechat.notify.PaySuccessCallBack;
import com.ygqh.baby.service.wechat.notify.YgMchPayPackage;
import com.ygqh.baby.utils.DateConvertUtils;

@Component
public class WxAppPayApi {
	protected final Logger logger = Logger.getLogger(this.getClass());
	protected final static WeixinRequestExecutor weixinExecutor = new WeixinRequestExecutor();

	@Autowired
	private FileService fileService;
	@Autowired
	private AppPaySuccessHandler appPaySuccessHandler;

	public PayRequest createPrePay(AppType appType, Long paymentCode, int totalFee, String ipAddress, String notifyUrl, String attach)
			throws WeixinPayException {
		WeixinPayAccount weixinPayAccount = WxAppUtils.wxAppPayAccount;

		YgMchPayPackage payPackage = new YgMchPayPackage(weixinPayAccount, null, "壹果订单", paymentCode.toString(), totalFee, notifyUrl, ipAddress, TradeType.APP);
		if (StringUtil.isNotBlank(attach)) {
			payPackage.setAttach(attach);
		}
		YgPay3Api ygPay3Api = new YgPay3Api(weixinPayAccount);
		PrePay prePay = ygPay3Api.createPrePay(payPackage);
		PayRequest payRequest = new PayRequest(prePay.getAppId(), "Sign=WXPay");
		payRequest.setPrepayId(prePay.getPrepayId());
		payRequest.setSignType(SignType.MD5);
		payRequest.setPartnerId(weixinPayAccount.getMchId());
		Map<String, String> map = new HashMap<>();
		map.put("appid", weixinPayAccount.getId());
		map.put("partnerid", weixinPayAccount.getMchId());
		map.put("prepayid", prePay.getPrepayId());
		map.put("package", "Sign=WXPay");
		map.put("noncestr", payRequest.getNonceStr());
		map.put("timestamp", payRequest.getTimeStamp());

		System.out.println(JSON.toJSON(map));
		payRequest.setPaySign(DigestUtil.paysignMd5(map, weixinPayAccount.getPaySignKey()));

		return payRequest;
	}

	public RefundResult refund(AppType appType, String returnCode, BigDecimal refundPrice, BigDecimal orderPrice, String orderPayCode) throws YgException {
		WeixinPayAccount weixinPayAccount = WxAppUtils.wxAppPayAccount;
		RefundResult result = null;
		try {

			InputStream inputStream = this.getCertIo(WxAppUtils.wxAppCertUrl);
			Pay3Api pay3Api = new Pay3Api(weixinPayAccount);
			IdQuery idQuery = new IdQuery(orderPayCode, IdType.TRADENO);
			result = pay3Api.refundApply(inputStream, idQuery, returnCode, orderPrice.doubleValue(), refundPrice.doubleValue(), CurrencyType.CNY,
					weixinPayAccount.getMchId());

		} catch (Exception e) {
			YgException exception = null;
			e.printStackTrace();
			if (e instanceof WeixinException) {
				exception = new YgException(((WeixinException) e).getErrorCode(), ((WeixinException) e).getErrorMsg());
				System.out.println(exception.getMessage());
			} else if (e instanceof IOException) {
				exception = new YgException("读取证书失败", e.toString());
			} else {
				exception = new YgException(e.getMessage());
			}
			throw exception;
		}
		return result;

	}

	private InputStream getCertIo(String certUrl) {
		InputStream inputStream = fileService.downloadIOFromOss(certUrl);
		return inputStream;
	}

	protected final static ExecutorService executorService = Executors.newFixedThreadPool(5);

	public String wxAppPayCallBack(String result) {
		String responseXml = new PayNotifyTemplate(result).execute(new PaySuccessCallBack() {
			@Override
			public void onSuccess(PayNotifyData payNotifyData) {
				executorService.execute(new Runnable() {
					public void run() {
						String attach = payNotifyData.getAttach();
						JSONObject params = JSON.parseObject(attach);

						String paymentCode = payNotifyData.getOut_trade_no();
						String transactionId = payNotifyData.getTransaction_id();
						int total_fee = Integer.parseInt(payNotifyData.getTotal_fee());
						BigDecimal totalPrice = new BigDecimal(total_fee).divide(new BigDecimal(100));
						Date paidTime = DateConvertUtils.parse(payNotifyData.getTime_end(), "yyyyMMddHHmmss");

						appPaySuccessHandler.paySuccess(PayType.WeChat, paymentCode, transactionId, totalPrice, paidTime, params);
					}

				});

			}
		});
		return responseXml;
	}

}
